Hi,
Just wanted to put an update for the CMakeLists.txt since I forgot to CC to
the mailing list, apologies.
Also, since I forgot to CC my previous email about this, maybe we just
remove glp_netgen_prob from netgen.c and glpk.h since it is not called and
causes linker error when building DLL on Windows since glp_netgen_prob is
listed in the .def file?
I saw the other possible change as mentioned in
https://www.mail-archive.com/[email protected]/msg01020.html; maybe that
could be done officially?
Best,
Derek
On Mon, Jan 29, 2024 at 3:43 PM Derek Huang <[email protected]> wrote:
> I see, thank you.
>
>
>
> So maybe we can just add these netgen.c changes to the upstream? Since it
> is definitely a bit strange to have only a public API function declaration
> without a definition.
>
>
>
> Best,
>
> Derek
>
cmake_minimum_required(VERSION 3.15)
##
# Usage
# =====
#
# This section provides some brief instructions on how to compile, test, and
# install GLPK using CMake. Although currently configured only for use on
# Windows, the config can be extended to support *nix systems as well.
#
# Note:
#
# This file can be split up into smaller .cmake files if desired. It is a few
# hundred lines long unfortunately in large part since the sources are all
# listed explicitly instead of using globs and because of the install logic.
#
# Windows
# -------
#
# The following items are values to be determined by the user. They are used in
# the build commands enclosed in brackets to distinguish them.
#
# Arch: Win32, x64
# Config: Debug, Release
# Prefix: (desired install root)
#
# Building
# ~~~~~~~~
#
# Note:
#
# Building dynamically, i.e. with -DBUILD_SHARED_LIBS=ON, will result in a
# linker error about an unresolved external symbol (glp_netgen_prob). The
# definition of this function is nowhere to be found in the GLPK source. To fix
# this, glp_netgen_prob needs to be removed from the .def file. It is also
# better that glp_netgen_prob is simply commented out from glpk.h too.
#
# Build static linking against C runtime dynamically + also build examples:
#
# cmake -S . -B build_windows_[Arch] -A [Arch]
# cmake --build build_windows_[Arch] --config [Config] -j
#
# Build dynamic linking against C runtime statically + no examples:
#
# cmake -S . -B build_windows_[Arch] -A [Arch] -DBUILD_SHARED_LIBS=ON ^
# -DGLPK_USE_STATIC_CRT=ON -DGLPK_BUILD_EXAMPLES=OFF
# cmake --build build_windows_[Arch] --config [Config] -j
#
# Build dynamic linking against C runtime dynamically + also build examples
# while installing with multi-configuration install tree:
#
# cmake -S . -B build_windows_[Arch] -A [Arch] -DBUILD_SHARED_LIBS=ON ^
# -DGLPK_INSTALL_MULTI_CONFIG=ON
# cmake --build build_windows_[Arch] --config [Config] -j
#
# Testing
# ~~~~~~~
#
# Note:
#
# Testing a dynamic build's example programs will result in an exit code of
# C0000135 since PATH must be updated or the DLL must be in the working
# directory for correct run-time loading. The example programs assume their
# inputs are in the current directory which makes this difficult.
#
# ctest --test-dir build_windows_[Arch] -C [Config] -j
#
# Install
# ~~~~~~~
#
# cmake --install build_windows_[Arch] --prefix [Prefix] --config [Config]
#
# If GLPK_INSTALL_MULTI_CONFIG is specified, and assuming that we are building
# shared libraries, the install tree looks like this:
#
# install_root/
# bin/
# Debug/
# glpk.dll
# glpsol.exe
# Release/
# glpk.dll
# glpsol.exe
# include/
# glpk.h
# lib/
# Debug/
# glpk.lib
# glpk.pdb
# Release/
# glpk.lib
#
# Otherwise, we have a flat install with "d" suffices, e.g.
#
# install_root/
# bin/
# glpk.dll
# glpkd.dll
# glpsol.exe
# glpsold.exe
# include/
# glpk.h
# lib/
# glpk.lib
# glpkd.lib
# glpkd.pdb
#
# GLPK version
set(GLPK_VERSION_MAJOR 5)
set(GLPK_VERSION_MINOR 0)
set(GLPK_VERSION ${GLPK_VERSION_MAJOR}.${GLPK_VERSION_MINOR})
project(
glpk
VERSION ${GLPK_VERSION}
DESCRIPTION "GNU Linear Programming Kit"
HOMEPAGE_URL "https://www.gnu.org/software/glpk/"
LANGUAGES C
)
# select static/shared library compilation
option(BUILD_SHARED_LIBS "Build GLPK library as shared" OFF)
# use static C runtime library. defaulted to OFF to match the CMake default of
# using MultiThreaded$<$<CONFIG:Debug>:Debug>DLL to select dynamic C runtime.
# see https://cmake.org/cmake/help/latest/prop_tgt/MSVC_RUNTIME_LIBRARY.html,
# https://learn.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features
option(GLPK_USE_STATIC_CRT "Link against C runtime statically" OFF)
# to separate Debug and Release libraries, which also link against debug and
# release C runtimes respectively (should never be mixed), add an extra layer
# of namespacing to lib and bin, e.g. lib/Debug, bin/Release, etc. for MSVC, if
# this is not specified, debug libraries + PDB is suffixed with "d"
option(GLPK_INSTALL_MULTI_CONFIG OFF)
# build example programs
option(GLPK_BUILD_EXAMPLES "Build the GLPK example programs" ON)
# only available for Windows currently
if(NOT WIN32)
message(FATAL_ERROR "CMake config is currently only usable for Windows")
endif()
# enable testing via ctest
include(CTest)
# check if multi-config or not
get_property(GLPK_BUILD_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(GLPK_BUILD_MULTI_CONFIG)
message(STATUS "Build generator: Multi-config")
else()
message(STATUS "Build generator: Single-config")
endif()
# static/shared library build
if(BUILD_SHARED_LIBS)
message(STATUS "GLPK build: Shared")
else()
message(STATUS "GLPK build: Static")
endif()
# link statically against C runtime library if requested
if(WIN32)
if(GLPK_USE_STATIC_CRT)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
message(STATUS "UCRT linkage: Static")
# link dynamically. this is the default but we set this explicitly
else()
set(CMAKE_MSVC_RUNTIME_LIBRARY
"MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
message(STATUS "UCRT linkage: Shared")
endif()
endif()
# multi-config installation (only for Windows)
if(WIN32 AND GLPK_INSTALL_MULTI_CONFIG)
message(STATUS "Installation: Multi")
else()
message(STATUS "Installation: Flat")
endif()
# example programs
if(GLPK_BUILD_EXAMPLES)
message(STATUS "Build examples: No")
else()
message(STATUS "Build examples: Yes")
endif()
# examples directory absolute path
set(GLPK_EXAMPLES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/examples)
# check if generating 32- or 64-bit code
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(GLPK_TARGET_64 ON)
set(GLPK_TARGET_32 OFF)
set(GLPK_WINDOWS_SUBDIR w64)
message(STATUS "Architecture: 64-bit")
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
set(GLPK_TARGET_64 OFF)
set(GLPK_TARGET_32 ON)
set(GLPK_WINDOWS_SUBDIR w32)
message(STATUS "Architecture: 32-bit")
else()
message(FATAL_ERROR "Incompatible pointer size, must be 8 or 4 bytes")
endif()
# compile flags
if(MSVC)
# TODO: increase warning level later? e.g. /W4, /Wall
add_compile_definitions(HAVE_CONFIG_H _CRT_SECURE_NO_WARNINGS)
add_compile_options(/W3)
else()
# TODO: fill in for *nix
endif()
# include directories
include_directories(
src
src/amd
src/api
src/bflib
src/colamd
src/draft
src/env
src/intopt
src/minisat
src/misc
src/mpl
src/npp
src/proxy
src/simplex
src/zlib
)
# add w32 or w64 as include for config.h appropriately
include_directories(${GLPK_WINDOWS_SUBDIR})
set(GLPK_CONFIG_H_DIR ${CMAKE_CURRENT_SOURCE_DIR}/${GLPK_WINDOWS_SUBDIR})
message(STATUS "config.h from: ${GLPK_WINDOWS_SUBDIR}")
# build GLPK library. maybe use wildcards? include .def for DLL
add_library(
glpk
src/amd/amd_1.c
src/amd/amd_2.c
src/amd/amd_aat.c
src/amd/amd_control.c
src/amd/amd_defaults.c
src/amd/amd_dump.c
src/amd/amd_info.c
src/amd/amd_order.c
src/amd/amd_post_tree.c
src/amd/amd_postorder.c
src/amd/amd_preprocess.c
src/amd/amd_valid.c
src/api/advbas.c
src/api/asnhall.c
src/api/asnlp.c
src/api/asnokalg.c
src/api/ckasn.c
src/api/ckcnf.c
src/api/cplex.c
src/api/cpp.c
src/api/cpxbas.c
src/api/graph.c
src/api/gridgen.c
src/api/intfeas1.c
src/api/maxffalg.c
src/api/maxflp.c
src/api/mcflp.c
src/api/mcfokalg.c
src/api/mcfrelax.c
src/api/minisat1.c
src/api/mpl.c
src/api/mps.c
src/api/netgen.c
src/api/npp.c
src/api/pript.c
src/api/prmip.c
src/api/prob1.c
src/api/prob2.c
src/api/prob3.c
src/api/prob4.c
src/api/prob5.c
src/api/prrngs.c
src/api/prsol.c
src/api/rdasn.c
src/api/rdcc.c
src/api/rdcnf.c
src/api/rdipt.c
src/api/rdmaxf.c
src/api/rdmcf.c
src/api/rdmip.c
src/api/rdprob.c
src/api/rdsol.c
src/api/rmfgen.c
src/api/strong.c
src/api/topsort.c
src/api/weak.c
src/api/wcliqex.c
src/api/wrasn.c
src/api/wrcc.c
src/api/wrcnf.c
src/api/wript.c
src/api/wrmaxf.c
src/api/wrmcf.c
src/api/wrmip.c
src/api/wrprob.c
src/api/wrsol.c
src/bflib/btf.c
src/bflib/btfint.c
src/bflib/fhv.c
src/bflib/fhvint.c
src/bflib/ifu.c
src/bflib/luf.c
src/bflib/lufint.c
src/bflib/scf.c
src/bflib/scfint.c
src/bflib/sgf.c
src/bflib/sva.c
src/colamd/colamd.c
src/draft/bfd.c
src/draft/bfx.c
src/draft/glpapi06.c
src/draft/glpapi07.c
src/draft/glpapi08.c
src/draft/glpapi09.c
src/draft/glpapi10.c
src/draft/glpapi12.c
src/draft/glpapi13.c
src/draft/glpios01.c
src/draft/glpios02.c
src/draft/glpios03.c
src/draft/glpios07.c
src/draft/glpios09.c
src/draft/glpios11.c
src/draft/glpios12.c
src/draft/glpipm.c
src/draft/glpmat.c
src/draft/glpscl.c
src/draft/glpssx01.c
src/draft/glpssx02.c
src/draft/lux.c
src/env/alloc.c
src/env/dlsup.c
src/env/env.c
src/env/error.c
src/env/stdc.c
src/env/stdout.c
src/env/stream.c
src/env/time.c
src/env/tls.c
src/intopt/cfg.c
src/intopt/cfg1.c
src/intopt/cfg2.c
src/intopt/clqcut.c
src/intopt/covgen.c
src/intopt/fpump.c
src/intopt/gmicut.c
src/intopt/gmigen.c
src/intopt/mirgen.c
src/intopt/spv.c
src/minisat/minisat.c
src/misc/avl.c
src/misc/bignum.c
src/misc/dimacs.c
src/misc/dmp.c
src/misc/ffalg.c
src/misc/fp2rat.c
src/misc/fvs.c
src/misc/gcd.c
src/misc/hbm.c
src/misc/jd.c
src/misc/keller.c
src/misc/ks.c
src/misc/mc13d.c
src/misc/mc21a.c
src/misc/mt1.c
src/misc/mygmp.c
src/misc/okalg.c
src/misc/qmd.c
src/misc/relax4.c
src/misc/rgr.c
src/misc/rng.c
src/misc/rng1.c
src/misc/round2n.c
src/misc/spm.c
src/misc/str2int.c
src/misc/str2num.c
src/misc/strspx.c
src/misc/strtrim.c
src/misc/triang.c
src/misc/wclique.c
src/misc/wclique1.c
src/mpl/mpl1.c
src/mpl/mpl2.c
src/mpl/mpl3.c
src/mpl/mpl4.c
src/mpl/mpl5.c
src/mpl/mpl6.c
src/mpl/mplsql.c
src/npp/npp1.c
src/npp/npp2.c
src/npp/npp3.c
src/npp/npp4.c
src/npp/npp5.c
src/npp/npp6.c
src/proxy/proxy.c
src/proxy/proxy1.c
src/simplex/spxat.c
src/simplex/spxchuzc.c
src/simplex/spxchuzr.c
src/simplex/spxlp.c
src/simplex/spxnt.c
src/simplex/spxprim.c
src/simplex/spxprob.c
src/simplex/spychuzc.c
src/simplex/spychuzr.c
src/simplex/spydual.c
src/zlib/adler32.c
src/zlib/compress.c
src/zlib/crc32.c
src/zlib/deflate.c
src/zlib/gzclose.c
src/zlib/gzlib.c
src/zlib/gzread.c
src/zlib/gzwrite.c
src/zlib/inffast.c
src/zlib/inflate.c
src/zlib/inftrees.c
src/zlib/trees.c
src/zlib/uncompr.c
src/zlib/zio.c
src/zlib/zutil.c
${GLPK_WINDOWS_SUBDIR}/glpk_${GLPK_VERSION_MAJOR}_${GLPK_VERSION_MINOR}.def
)
# config.h copying from config_VC. w32 and w64 are same but we choose
add_custom_command(
TARGET glpk PRE_BUILD
COMMAND
${CMAKE_COMMAND} -E copy_if_different ${GLPK_CONFIG_H_DIR}/config_VC
${GLPK_CONFIG_H_DIR}/config.h
COMMENT "Copying config_VC to config.h"
VERBATIM
)
# glpk.h is the public header
set_target_properties(glpk PROPERTIES PUBLIC_HEADER src/glpk.h)
# if not using multi-config install, suffix "d" to glpk
if(MSVC AND NOT GLPK_INSTALL_MULTI_CONFIG)
set_target_properties(glpk PROPERTIES OUTPUT_NAME glpk$<$<CONFIG:Debug>:d>)
endif()
# build glpsol
add_executable(glpsol examples/glpsol.c)
target_link_libraries(glpsol PRIVATE glpk)
# if not using multi-config install, suffix "d" to glpsol
if(MSVC AND NOT GLPK_INSTALL_MULTI_CONFIG)
set_target_properties(glpsol PROPERTIES OUTPUT_NAME
glpsol$<$<CONFIG:Debug>:d>)
endif()
# build examples
if(GLPK_BUILD_EXAMPLES)
add_executable(iptsamp examples/iptsamp.c)
target_link_libraries(iptsamp PRIVATE glpk)
add_executable(mplsamp1 examples/mplsamp1.c)
target_link_libraries(mplsamp1 PRIVATE glpk)
add_executable(mplsamp2 examples/mplsamp2.c)
target_link_libraries(mplsamp2 PRIVATE glpk)
# aborts since glp_netgen disabled due to licensing problems
# add_executable(netgen examples/netgen.c)
# target_link_libraries(netgen PRIVATE glpk)
add_executable(nppsamp examples/nppsamp.c)
target_link_libraries(nppsamp PRIVATE glpk)
add_executable(sample examples/sample.c)
target_link_libraries(sample PRIVATE glpk)
add_executable(spxsamp1 examples/spxsamp1.c)
target_link_libraries(spxsamp1 PRIVATE glpk)
add_executable(spxsamp2 examples/spxsamp2.c)
target_link_libraries(spxsamp2 PRIVATE glpk)
endif()
# add glpsol as ctest test
add_test(NAME "glpsol_version" COMMAND glpsol --version)
add_test(
NAME "glpsol_murtagh"
COMMAND glpsol --mps ${CMAKE_CURRENT_SOURCE_DIR}/examples/murtagh.mps --max
)
# add examples as additional tests
if(GLPK_BUILD_EXAMPLES)
add_test(NAME iptsamp COMMAND iptsamp WORKING_DIRECTORY
${GLPK_EXAMPLES_DIR})
add_test(NAME mplsamp1 COMMAND mplsamp1 WORKING_DIRECTORY
${GLPK_EXAMPLES_DIR})
add_test(NAME mplsamp2 COMMAND mplsamp2 WORKING_DIRECTORY
${GLPK_EXAMPLES_DIR})
# add_test(NAME netgen COMMAND netgen WORKING_DIRECTORY
${GLPK_EXAMPLES_DIR})
add_test(NAME nppsamp COMMAND nppsamp WORKING_DIRECTORY
${GLPK_EXAMPLES_DIR})
add_test(NAME sample COMMAND sample WORKING_DIRECTORY ${GLPK_EXAMPLES_DIR})
add_test(NAME spxsamp1 COMMAND spxsamp1 WORKING_DIRECTORY
${GLPK_EXAMPLES_DIR})
add_test(NAME spxsamp2 COMMAND spxsamp2 WORKING_DIRECTORY
${GLPK_EXAMPLES_DIR})
endif()
# targets to install. glpk includes the glpk.h header
set(GLPK_INSTALL_TARGETS glpk glpsol)
# install library and glpsol when cmake --install is invoked
if(MSVC)
# Debug config should also install PDB files. they go to lib if libraries
# are static, bin if libraries are DLL for debugging convenience
if(BUILD_SHARED_LIBS)
set(GLPK_PDB_INSTALL_SUBDIR bin)
else()
set(GLPK_PDB_INSTALL_SUBDIR lib)
endif()
# multi-config installation
if(GLPK_INSTALL_MULTI_CONFIG)
install(
TARGETS ${GLPK_INSTALL_TARGETS}
RUNTIME DESTINATION bin/$<CONFIG>
LIBRARY DESTINATION lib/$<CONFIG>
ARCHIVE DESTINATION lib/$<CONFIG>
PUBLIC_HEADER DESTINATION include
COMPONENT glpk
)
# Debug config should also install PDB files. they go to lib if
# libraries are static, bin if libraries are DLL
if(BUILD_SHARED_LIBS)
set(GLPK_PDB_INSTALL_SUBDIR bin)
else()
set(GLPK_PDB_INSTALL_SUBDIR lib)
endif()
# install PDB file for Debug config only
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/Debug/glpk.pdb
CONFIGURATIONS Debug
DESTINATION ${GLPK_PDB_INSTALL_SUBDIR}/Debug
COMPONENT glpk
)
# flat installation where artifacts are suffixed with "d"
else()
install(
TARGETS ${GLPK_INSTALL_TARGETS}
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
PUBLIC_HEADER DESTINATION include
COMPONENT glpk
)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/Debug/glpkd.pdb
CONFIGURATIONS Debug
DESTINATION ${GLPK_PDB_INSTALL_SUBDIR}
COMPONENT glpk
)
endif()
# typical flat *nix installation
# TODO: for *nix, need pkg-config stuff too, etc.
else()
install(
TARGETS ${GLPK_INSTALL_TARGETS}
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
PUBLIC_HEADER DESTINATION include
COMPONENT glpk
)
endif()