Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,10 @@ if(MSVC)
# warning level 3
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3")

# Remove unreferenced COMDATs (functions/data) before they reach the linker.
# Shrinks object files; does NOT reduce dllexport'd symbol counts (verified empirically).
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:inline")

# warning level 4 - DLM: we should shoot for this
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")

Expand Down Expand Up @@ -1671,7 +1675,9 @@ if (MSVC)
# within the same library. This may result in less efficient function calls.

# The potential inefficiency goes away if we use LTO linking
target_link_libraries(openstudiolib PRIVATE -IGNORE:4217,4049)
foreach(_os_lib openstudiolib openstudiomodellib openstudioepmodellib openstudioutilitieslib)
target_link_libraries(${_os_lib} PRIVATE -IGNORE:4217,4049)
endforeach()
if(CMAKE_SIZEOF_VOID_P EQUAL 8) # only applies to 64 bit windows platforms
if (BUILD_RUBY_BINDINGS)
target_link_libraries(openstudio_rb PRIVATE -IGNORE:4217,4049)
Expand Down
2 changes: 1 addition & 1 deletion python/engine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ if(BUILD_TESTING)
set(pythonengine_test_depends
openstudio_scriptengine
openstudiolib
openstudio_epmodel
openstudio_epmodel_headers
fmt::fmt
)

Expand Down
2 changes: 1 addition & 1 deletion ruby/engine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ if(BUILD_TESTING)
set(rubyengine_test_depends
openstudio_scriptengine
openstudiolib
openstudio_epmodel
openstudio_epmodel_headers
fmt::fmt
)

Expand Down
19 changes: 18 additions & 1 deletion src/epmodel/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2751,6 +2751,23 @@ set(${target_name}_depends
set(${target_name}_depends ${${target_name}_depends} PARENT_SCOPE)

target_compile_definitions(${target_name} PRIVATE openstudio_epmodel_EXPORTS SHARED_OS_LIBS)

# Headers-only INTERFACE target: gives consumers epmodel's per-subfolder include
# directories without pulling in its OBJECT library's actual object files. On MSVC,
# openstudio_epmodel's objects already live in openstudioepmodellib.dll; any consumer
# that links both openstudio_epmodel directly AND openstudiolib (which PUBLIC-links
# openstudioepmodellib) gets the same symbols twice -- once as real definitions, once
# as the DLL's import-lib thunks -- which MSVC rejects (LNK2005). Consumers that only
# need to compile against epmodel headers (not embed its objects) should link this
# instead of openstudio_epmodel.
add_library(openstudio_epmodel_headers INTERFACE)
target_include_directories(openstudio_epmodel_headers INTERFACE
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/HVACComponent
${CMAKE_CURRENT_SOURCE_DIR}/ModelObject
${CMAKE_CURRENT_SOURCE_DIR}/scaffolds
${CMAKE_CURRENT_SOURCE_DIR}/StraightComponent
${CMAKE_CURRENT_SOURCE_DIR}/ShadingMaterial)

target_include_directories(${target_name} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/HVACComponent
${CMAKE_CURRENT_SOURCE_DIR}/ModelObject
${CMAKE_CURRENT_SOURCE_DIR}/scaffolds
Expand Down Expand Up @@ -3626,7 +3643,7 @@ set(${target_name}_test_src

set(${target_name}_test_depends
openstudiolib
openstudio_epmodel
openstudio_epmodel_headers
)

CREATE_SRC_GROUPS("${${target_name}_test_src}")
Expand Down
7 changes: 6 additions & 1 deletion src/epmodel/EPModelSwig.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,12 @@ macro(make_epmodel_swig_bindings NAME SIMPLENAME KEY_I_FILE I_FILES PARENT_TARGE
target_include_directories(${python_target} PRIVATE ${common_swig_include_dirs})
target_include_directories(${python_target} SYSTEM PRIVATE ${Python_INCLUDE_DIRS})
target_compile_definitions(${python_target} PRIVATE SHARED_OS_LIBS SWIG_PYTHON_SILENT_MEMLEAK)
target_link_libraries(${python_target} PUBLIC ${PARENT_TARGET} ${${PARENT_TARGET}_depends})
# Do NOT link PARENT_TARGET (the openstudio_epmodel OBJECT library) directly here:
# every python binding target already gets the real symbols via openstudiolib
# (linked in python/module/CMakeLists.txt). Linking both directly embeds epmodel's
# object code twice, which MSVC rejects (LNK2005) since its import-lib thunks for
# openstudioepmodellib collide with the directly-linked definitions.
target_link_libraries(${python_target} PUBLIC ${${PARENT_TARGET}_depends})
add_dependencies(${python_target} ${PARENT_TARGET})

if(MSVC)
Expand Down
117 changes: 95 additions & 22 deletions src/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,28 +1,99 @@

# Some operating systems don't like compiling a library with
# no source files
add_library(openstudiolib SHARED empty.cpp)

if(MSVC)
# MSVC import libraries (and the DLL export ordinal table) are limited to 65,535 exported
# symbols (LNK1189). model + epmodel together export ~123,000 unique symbols, far beyond
# that limit, so on Windows the object libraries are split across four DLLs:
#
# openstudioutilitieslib
# ▲ ▲
# openstudiomodellib openstudioepmodellib
# ▲ ▲
# openstudiolib
#
# openstudiolib keeps its name and PUBLIC-links the others so that no consumer
# (CLI, ruby/python/csharp bindings, tests) needs any change.
# Each OBJECT library still lands in exactly one DLL, so the per-component
# openstudio_<name>_EXPORTS / <NAME>_API macros produce correct dllexport/dllimport.
#
# openstudio_osversion goes in openstudiomodellib (not the top-level openstudiolib)
# because model/Model.cpp calls osversion::VersionTranslator directly (Model::load),
# while osversion links openstudio_model's own dependency chain -- a genuine mutual
# dependency that only compiles when both land in the same DLL.
add_library(openstudioutilitieslib SHARED empty.cpp)
target_link_libraries(
openstudioutilitieslib
PRIVATE
openstudio_utilities
)

target_link_libraries(
openstudiolib
PRIVATE
openstudio_utilities
openstudio_airflow
openstudio_model
openstudio_modelica
openstudio_energyplus
openstudio_epmodel
openstudio_epjson
openstudio_alfalfa
openstudio_measure
openstudio_osversion
openstudio_sdd
openstudio_isomodel
openstudio_gbxml
openstudio_gltf
openstudio_radiance
)
add_library(openstudiomodellib SHARED empty.cpp)
target_link_libraries(
openstudiomodellib
PRIVATE
openstudio_model
openstudio_energyplus
openstudio_osversion
PUBLIC
openstudioutilitieslib
)

add_library(openstudioepmodellib SHARED empty.cpp)
target_link_libraries(
openstudioepmodellib
PRIVATE
openstudio_epmodel
PUBLIC
openstudioutilitieslib
)

add_library(openstudiolib SHARED empty.cpp)
target_link_libraries(
openstudiolib
PRIVATE
openstudio_airflow
openstudio_modelica
openstudio_epjson
openstudio_alfalfa
openstudio_measure
openstudio_sdd
openstudio_isomodel
openstudio_gbxml
openstudio_gltf
openstudio_radiance
PUBLIC
openstudiomodellib
openstudioepmodellib
)

set(openstudio_lib_targets openstudiolib openstudiomodellib openstudioepmodellib openstudioutilitieslib)
else()
add_library(openstudiolib SHARED empty.cpp)

target_link_libraries(
openstudiolib
PRIVATE
openstudio_utilities
openstudio_airflow
openstudio_model
openstudio_modelica
openstudio_energyplus
openstudio_epmodel
openstudio_epjson
openstudio_alfalfa
openstudio_measure
openstudio_osversion
openstudio_sdd
openstudio_isomodel
openstudio_gbxml
openstudio_gltf
openstudio_radiance
)

set(openstudio_lib_targets openstudiolib)
endif()

target_link_libraries(
openstudiolib
Expand All @@ -36,7 +107,9 @@ target_link_libraries(
fmt::fmt
)

target_compile_definitions(openstudiolib INTERFACE "-DSHARED_OS_LIBS")
foreach(_os_lib IN LISTS openstudio_lib_targets)
target_compile_definitions(${_os_lib} INTERFACE "-DSHARED_OS_LIBS")
endforeach()

# We cannot make the libs that make up the shared library public dependency at all, if we do
# then we have to export and install them as well, which we probably don't want to do.
Expand All @@ -59,7 +132,7 @@ target_include_directories(
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/src>
)

install(TARGETS openstudiolib
install(TARGETS ${openstudio_lib_targets}
EXPORT openstudio
DESTINATION ${LIB_DESTINATION_DIR}
COMPONENT "CLI" # CLI is no longer self-contained, it needs it
Expand Down
4 changes: 2 additions & 2 deletions src/measure/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ CREATE_SRC_GROUPS("${${target_name}_src}")
CREATE_SRC_GROUPS("${${target_name}_swig_src}")

set(${target_name}_depends
openstudio_epmodel
openstudio_epmodel_headers
${openstudio_osversion_depends}
)
set(${target_name}_depends ${${target_name}_depends} PARENT_SCOPE)
Expand All @@ -63,7 +63,7 @@ add_dependencies(${target_name} GenerateIddFactoryRun)
set(${target_name}_test_depends
${COREFOUNDATION_LIBRARY}
openstudiolib
openstudio_epmodel
openstudio_epmodel_headers
fmt::fmt
)

Expand Down
2 changes: 1 addition & 1 deletion src/workflow/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ add_library(openstudio_workflow
Timer.cpp
)

target_link_libraries(openstudio_workflow PUBLIC openstudiolib openstudio_epmodel)
target_link_libraries(openstudio_workflow PUBLIC openstudiolib openstudio_epmodel_headers)

if(BUILD_TESTING)
set(openstudio_workflow_test_depends
Expand Down
Loading