From dd56308bde0cf7cbad3d02acaa28158c328067ad Mon Sep 17 00:00:00 2001 From: dev Date: Fri, 1 Dec 2023 10:51:28 +0100 Subject: [PATCH] [client,mac] Simplify builder * Build MacFreeRDP as normal application, let the bundling out of building * Add a bunding script allowing to create a MacFreeRDP with all dependencies installed --- client/Mac/CMakeLists.txt | 201 +++++-------------- client/Mac/MRDPView.m | 43 ++-- client/Mac/PasswordDialog.m | 10 +- client/Mac/cli/AppDelegate.h | 4 +- client/Mac/cli/AppDelegate.m | 6 +- client/Mac/cli/CMakeLists.txt | 148 ++++++-------- client/Mac/cli/{Info.plist => Info.plist.in} | 0 client/Mac/cli/PkgInfo.in | 1 + cmake/ConfigureRPATH.cmake | 3 +- scripts/bundle-mac-os.sh | 134 +++++++++++++ 10 files changed, 282 insertions(+), 268 deletions(-) rename client/Mac/cli/{Info.plist => Info.plist.in} (100%) create mode 100644 client/Mac/cli/PkgInfo.in create mode 100755 scripts/bundle-mac-os.sh diff --git a/client/Mac/CMakeLists.txt b/client/Mac/CMakeLists.txt index f2b016195..cc178f153 100644 --- a/client/Mac/CMakeLists.txt +++ b/client/Mac/CMakeLists.txt @@ -12,36 +12,21 @@ endif() list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/) include(PreventInSourceBuilds) -set(MODULE_NAME "MacFreeRDP-library") -set(MODULE_OUTPUT_NAME "MacFreeRDP") -set(MODULE_PREFIX "FREERDP_CLIENT_MAC_LIBRARY") +find_library(FOUNDATION_LIBRARY Foundation REQUIRED) +find_library(COCOA_LIBRARY Cocoa REQUIRED) +find_library(APPKIT_LIBRARY AppKit REQUIRED) +find_library(IOKIT_LIBRARY IOKit REQUIRED) +find_library(COREGRAPHICS_LIBRARY CoreGraphics REQUIRED) -find_library(FOUNDATION_LIBRARY Foundation) -find_library(COCOA_LIBRARY Cocoa) -find_library(APPKIT_LIBRARY AppKit) -find_library(IOKIT_LIBRARY IOKit) -find_library(COREGRAPHICS_LIBRARY CoreGraphics) - -mark_as_advanced(COCOA_LIBRARY FOUNDATION_LIBRARY APPKIT_LIBRARY) set(EXTRA_LIBS ${COCOA_LIBRARY} ${FOUNDATION_LIBRARY} ${APPKIT_LIBRARY} ${IOKIT_LIBRARY}) -string(TIMESTAMP VERSION_YEAR "%Y") -set(MACOSX_BUNDLE_INFO_STRING "${MODULE_OUTPUT_NAME}") -set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.freerdp.mac") -set(MACOSX_BUNDLE_BUNDLE_IDENTIFIER "FreeRDP-library.Mac") -set(MACOSX_BUNDLE_LONG_VERSION_STRING "MacFreeRDP library Version ${FREERDP_VERSION}") -set(MACOSX_BUNDLE_BUNDLE_NAME "${MODULE_OUTPUT_NAME}") -set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${FREERDP_VERSION}) -set(MACOSX_BUNDLE_BUNDLE_VERSION ${FREERDP_VERSION}) -set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2013-${VERSION_YEAR}. All Rights Reserved.") - -set(${MODULE_PREFIX}_XIBS +set(XIBS CertificateDialog.xib PasswordDialog.xib) -set(${MODULE_PREFIX}_SOURCES "") +set(SOURCES "") -set(${MODULE_PREFIX}_OBJECTIVE_SOURCES +set(OBJECTIVE_SOURCES main.m mf_client.m MRDPCursor.m @@ -51,9 +36,9 @@ set(${MODULE_PREFIX}_OBJECTIVE_SOURCES CertificateDialog.m PasswordDialog.m) -list(APPEND ${MODULE_PREFIX}_SOURCES ${${MODULE_PREFIX}_OBJECTIVE_SOURCES}) +list(APPEND SOURCES ${OBJECTIVE_SOURCES}) -set(${MODULE_PREFIX}_HEADERS +set(HEADERS mfreerdp.h mf_client.h MRDPCursor.h @@ -63,150 +48,58 @@ set(${MODULE_PREFIX}_HEADERS CertificateDialog.h PasswordDialog.h) -set(${MODULE_PREFIX}_RESOURCES "en.lproj/InfoPlist.strings") +set(RESOURCES "en.lproj/InfoPlist.strings") # Include XIB file in Xcode resources. if("${CMAKE_GENERATOR}" MATCHES "Xcode") - message(STATUS "Adding Xcode XIB resources for ${MODULE_NAME}") - set(${MODULE_PREFIX}_RESOURCES ${${MODULE_PREFIX}_RESOURCES} ${${MODULE_PREFIX}_XIBS}) + message(STATUS "Adding Xcode XIB resources for ${MODULE_NAME}") + list(APPEND RESOURCES ${XIBS}) + set(IS_XCODE ON) endif() -add_library(${MODULE_NAME} - SHARED + +add_library(${PROJECT_NAME} ../common/client.c - ${${MODULE_PREFIX}_SOURCES} - ${${MODULE_PREFIX}_HEADERS} - ${${MODULE_PREFIX}_RESOURCES}) + ${SOURCES} + ${HEADERS} + ${RESOURCES}) -set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "${MODULE_OUTPUT_NAME}") +set(LIBS + ${EXTRA_LIBS} + freerdp-client + ) -# configures the framework to always be looked for in the application bundle in the Frameworks sub-folder. -set_target_properties(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_INSTALL_PATH @executable_path/../Frameworks/) +target_link_libraries(${PROJECT_NAME} PUBLIC ${LIBS}) -set_target_properties(${MODULE_NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY_DEBUG ${EXECUTABLE_OUTPUT_PATH} - RUNTIME_OUTPUT_DIRECTORY_RELEASE ${EXECUTABLE_OUTPUT_PATH}) +set_target_properties(${PROJECT_NAME} PROPERTIES RESOURCE "${RESOURCES}") -set_target_properties(${MODULE_NAME} PROPERTIES - FRAMEWORK TRUE - MACOSX_FRAMEWORK_IDENTIFIER com.awakecoding.${MODULE_NAME} - FRAMEWORK_VERSION ${FREERDP_VERSION} - MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${FREERDP_VERSION} - MACOSX_FRAMEWORK_BUNDLE_BUNDLE_VERSION ${FREERDP_VERSION} - INSTALL_NAME_DIR "@executable_path/../Frameworks" - MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist) +if (NOT IS_XCODE) + find_program(IBTOOL ibtool REQUIRED + HINTS + "/usr/bin" + "${OSX_DEVELOPER_ROOT}/usr/bin" + ) -set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${EXTRA_LIBS} freerdp-client) -set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr freerdp) + # Compile the .xib files using the 'ibtool' program with the destination being the app package + foreach(xib ${XIBS}) + get_filename_component(XIB_WE ${xib} NAME_WE) + set(NIB ${CMAKE_CURRENT_BINARY_DIR}/${XIB_WE}.nib) + list(APPEND NIBS ${NIB}) -target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + add_custom_command (TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${IBTOOL} --errors --warnings --notices --output-format human-readable-text + --compile ${NIB} ${CMAKE_CURRENT_SOURCE_DIR}/${xib} + COMMENT "Compiling ${xib}") + endforeach() -# Set a list of the dependent targets used by the application. There should be a way to get this list automatically -# from cmake, but for now I put it down manually. I got the references by calling "otool -L MacFreeRDP-client" - -set(DEPENDENCIES "") - -foreach(LIB ${${MODULE_PREFIX}_LIBS}) - get_target_property(LOCATION ${LIB} LOCATION) - if(NOT ${LOCATION} MATCHES ".*-NOTFOUND") - list(APPEND DEPENDENCIES ${LIB}) - endif() -endforeach() - -set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Client/Mac") - -if(CMAKE_GENERATOR MATCHES "Ninja") - if (NOT ${CONFIGURATION} STREQUAL "") - set(safe_configuration "$CONFIGURATION") - else() - set(safe_configuration "") - endif() -else() - set(safe_configuration "$(CONFIGURATION)") + install(FILES ${NIBS} DESTINATION ${CMAKE_INSTALL_DATADIR}) endif() -if (${BUILD_SHARED_LIBS}) - # Add a post-build event to copy the dependent libraries in the framework bundle - # Call install_name_tool to reassign the library install name - foreach(LIB ${DEPENDENCIES}) - # message("adding post-build dependency: ${LIB}") - add_custom_command(TARGET ${MODULE_NAME} POST_BUILD - COMMAND "${CMAKE_COMMAND}" -E copy - "$" - "${CMAKE_CURRENT_BINARY_DIR}/${safe_configuration}/${MODULE_OUTPUT_NAME}.framework/Contents/$" - COMMENT "Copying ${LIB} to output directory" - COMMAND install_name_tool -change "$" - "@executable_path/../Frameworks/${MODULE_OUTPUT_NAME}.framework/Contents/$" - "${CMAKE_CURRENT_BINARY_DIR}/${safe_configuration}/${MODULE_OUTPUT_NAME}.framework/${MODULE_OUTPUT_NAME}" - COMMENT Setting install name for ${LIB} - COMMAND "${CMAKE_COMMAND}" -E echo install_name_tool -change "$" - "@executable_path/../Frameworks/${MODULE_OUTPUT_NAME}.framework/Contents/$" - "${CMAKE_CURRENT_BINARY_DIR}/${safe_configuration}/${MODULE_OUTPUT_NAME}.framework/${MODULE_OUTPUT_NAME}") - endforeach() - # Call install_name_tool to reassign the library install names in dependent libraries - foreach(DEST ${DEPENDENCIES}) - foreach(LIB ${DEPENDENCIES}) - # message("adding post-build dependency: ${LIB}") - add_custom_command(TARGET ${MODULE_NAME} POST_BUILD - COMMAND install_name_tool -change "$" - "@executable_path/../Frameworks/${MODULE_OUTPUT_NAME}.framework/Contents/$" - "${CMAKE_CURRENT_BINARY_DIR}/${safe_configuration}/${MODULE_OUTPUT_NAME}.framework/Contents/$" - COMMENT Setting install name for ${LIB} in module ${DEST}) - endforeach() - endforeach() - -endif() - -# Add post-build NIB file generation in unix makefiles. XCode handles this implicitly. -# if(NOT "${CMAKE_GENERATOR}" MATCHES "Xcode") - message(STATUS "Adding post-build NIB file generation event for ${MODULE_NAME}") - - # Make sure we can find the 'ibtool' program. If we can NOT find it we - # skip generation of this project - find_program(IBTOOL ibtool HINTS "/usr/bin" "${OSX_DEVELOPER_ROOT}/usr/bin") - if (${IBTOOL} STREQUAL "IBTOOL-NOTFOUND") - message(SEND_ERROR "ibtool can not be found and is needed to compile the .xib files. It should have been installed with - the Apple developer tools. The default system paths were searched in addition to ${OSX_DEVELOPER_ROOT}/usr/bin") - endif() - - # Make sure the 'Resources' Directory is correctly created before we build - add_custom_command(TARGET ${MODULE_NAME} PRE_BUILD - COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/${safe_configuration}/${MODULE_OUTPUT_NAME}.framework/Versions/${MACOSX_BUNDLE_SHORT_VERSION_STRING}/Resources) - - # Compile the .xib files using the 'ibtool' program with the destination being the app package - foreach(xib ${${MODULE_PREFIX}_XIBS}) - get_filename_component(XIB_WE ${xib} NAME_WE) - - add_custom_command (TARGET ${MODULE_NAME} POST_BUILD - COMMAND ${IBTOOL} --errors --warnings --notices --output-format human-readable-text - --compile ${CMAKE_CURRENT_BINARY_DIR}/${safe_configuration}/${MODULE_OUTPUT_NAME}.framework/Versions/${MACOSX_BUNDLE_SHORT_VERSION_STRING}/Resources/${XIB_WE}.nib ${CMAKE_CURRENT_SOURCE_DIR}/${xib} - COMMENT "Compiling ${xib}") - endforeach() -# endif() - -set(MAC_LIB_FRAMEWORK_HEADERS "") -# Copy the public header files into the framework -foreach(HEADER ${${MODULE_PREFIX}_HEADERS}) - #message("adding post-build dependency: ${MODULE_NAME} ${HEADER}") - if( POLICY CMP0058 ) - set(NinjaByproducts BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/${CONFIGURATION}/${MODULE_OUTPUT_NAME}.framework/Headers/${HEADER}) - endif() - add_custom_command(TARGET ${MODULE_NAME} POST_BUILD - COMMAND ditto ${CMAKE_CURRENT_SOURCE_DIR}/${HEADER} ${CMAKE_CURRENT_BINARY_DIR}/${safe_configuration}/${MODULE_OUTPUT_NAME}.framework/Headers/ - ${NinjaByproducts} - COMMENT Copying public header files to ${MODULE_NAME}) - list(APPEND MAC_LIB_FRAMEWORK_HEADERS ${CMAKE_CURRENT_BINARY_DIR}/${CONFIGURATION}/${MODULE_OUTPUT_NAME}.framework/Headers/${HEADER}) -endforeach() -add_custom_target( - prepare-framework-headers - DEPENDS ${MAC_LIB_FRAMEWORK_HEADERS} -) - -# Copy the FreeRDP header files into the framework -add_custom_command(TARGET ${MODULE_NAME} POST_BUILD - COMMAND ditto ${CMAKE_SOURCE_DIR}/include/freerdp ${CMAKE_CURRENT_BINARY_DIR}/${safe_configuration}/${MODULE_OUTPUT_NAME}.framework/Headers/freerdp - COMMAND ditto ${CMAKE_SOURCE_DIR}/winpr/include/winpr ${CMAKE_CURRENT_BINARY_DIR}/${CONFIGURATION}/${MODULE_OUTPUT_NAME}.framework/Headers/winpr - COMMENT Copying FreeRDP header files to ${MODULE_NAME}) +install(TARGETS ${PROJECT_NAME} + COMPONENT client + RESOURCE DESTINATION ${CMAKE_INSTALL_DATADIR} + ) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) add_subdirectory(cli) diff --git a/client/Mac/MRDPView.m b/client/Mac/MRDPView.m index 4eb0560c9..6c82753c3 100644 --- a/client/Mac/MRDPView.m +++ b/client/Mac/MRDPView.m @@ -721,10 +721,10 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type) formatString = [[NSString alloc] initWithData:formatData encoding:NSUTF8StringEncoding]; - const char *data = [formatString UTF8String]; - const size_t size = strlen(data) + 1; + const char *data = [formatString cStringUsingEncoding:NSUTF8StringEncoding]; + const size_t dataLen = [formatString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; formatId = ClipboardRegisterFormat(mfc->clipboard, "text/plain"); - ClipboardSetData(mfc->clipboard, formatId, data, size); + ClipboardSetData(mfc->clipboard, formatId, data, dataLen + 1); [formatString release]; formatMatch = TRUE; @@ -950,6 +950,13 @@ static BOOL mac_show_auth_dialog(MRDPView *view, NSString *title, char **usernam if (*domain) dialog.domain = [NSString stringWithCString:*domain encoding:NSUTF8StringEncoding]; + free(*username); + free(*password); + free(*domain); + *username = NULL; + *password = NULL; + *domain = NULL; + dispatch_sync(dispatch_get_main_queue(), ^{ [dialog performSelectorOnMainThread:@selector(runModal:) withObject:[view window] @@ -959,31 +966,33 @@ static BOOL mac_show_auth_dialog(MRDPView *view, NSString *title, char **usernam if (ok) { - size_t ulen, plen, dlen; const char *submittedUsername = [dialog.username cStringUsingEncoding:NSUTF8StringEncoding]; - ulen = (strlen(submittedUsername) + 1) * sizeof(char); - *username = malloc(ulen); + const size_t submittedUsernameLen = + [dialog.username lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; + if (submittedUsername && (submittedUsernameLen > 0)) + *username = strndup(submittedUsername, submittedUsernameLen); if (!(*username)) return FALSE; - sprintf_s(*username, ulen, "%s", submittedUsername); const char *submittedPassword = [dialog.password cStringUsingEncoding:NSUTF8StringEncoding]; - plen = (strlen(submittedPassword) + 1) * sizeof(char); - *password = malloc(plen); + const size_t submittedPasswordLen = + [dialog.password lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; + if (submittedPassword && (submittedPasswordLen > 0)) + *password = strndup(submittedPassword, submittedPasswordLen); if (!(*password)) return FALSE; - sprintf_s(*password, plen, "%s", submittedPassword); const char *submittedDomain = [dialog.domain cStringUsingEncoding:NSUTF8StringEncoding]; - dlen = (strlen(submittedDomain) + 1) * sizeof(char); - *domain = malloc(dlen); - - if (!(*domain)) - return FALSE; - - sprintf_s(*domain, dlen, "%s", submittedDomain); + const size_t submittedDomainLen = + [dialog.domain lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; + if (submittedDomain && (submittedDomainLen > 0)) + { + *domain = strndup(submittedDomain, submittedDomainLen); + if (!(*domain)) + return FALSE; + } } return ok; diff --git a/client/Mac/PasswordDialog.m b/client/Mac/PasswordDialog.m index f4c520bec..aabb102a2 100644 --- a/client/Mac/PasswordDialog.m +++ b/client/Mac/PasswordDialog.m @@ -79,8 +79,12 @@ [self.usernameText.stringValue cStringUsingEncoding:NSUTF8StringEncoding], &submittedUser, &submittedDomain)) { - self.username = [NSString stringWithCString:submittedUser encoding:NSUTF8StringEncoding]; - self.domain = [NSString stringWithCString:submittedDomain encoding:NSUTF8StringEncoding]; + if (submittedUser) + self.username = [NSString stringWithCString:submittedUser + encoding:NSUTF8StringEncoding]; + if (submittedDomain) + self.domain = [NSString stringWithCString:submittedDomain + encoding:NSUTF8StringEncoding]; } else { @@ -88,6 +92,8 @@ } self.password = self.passwordText.stringValue; + free(submittedUser); + free(submittedDomain); [NSApp stopModalWithCode:TRUE]; } diff --git a/client/Mac/cli/AppDelegate.h b/client/Mac/cli/AppDelegate.h index 64b261149..e860039ea 100644 --- a/client/Mac/cli/AppDelegate.h +++ b/client/Mac/cli/AppDelegate.h @@ -7,8 +7,8 @@ // #import -#import -#import +#import +#import @interface AppDelegate : NSObject { diff --git a/client/Mac/cli/AppDelegate.m b/client/Mac/cli/AppDelegate.m index 6c732d68a..7bf63a0f2 100644 --- a/client/Mac/cli/AppDelegate.m +++ b/client/Mac/cli/AppDelegate.m @@ -7,9 +7,9 @@ // #import "AppDelegate.h" -#import "MacFreeRDP/mfreerdp.h" -#import "MacFreeRDP/mf_client.h" -#import "MacFreeRDP/MRDPView.h" +#import +#import +#import #import #import diff --git a/client/Mac/cli/CMakeLists.txt b/client/Mac/cli/CMakeLists.txt index 65213c4ee..c175070bc 100644 --- a/client/Mac/cli/CMakeLists.txt +++ b/client/Mac/cli/CMakeLists.txt @@ -4,14 +4,10 @@ project(MacFreeRDP) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/) include(PreventInSourceBuilds) -set(MODULE_NAME "MacFreeRDP") -set(MODULE_OUTPUT_NAME "MacFreeRDP") -set(MODULE_PREFIX "FREERDP_CLIENT_MAC_CLIENT") - # Import libraries -find_library(FOUNDATION_LIBRARY Foundation) -find_library(COCOA_LIBRARY Cocoa) -find_library(APPKIT_LIBRARY AppKit) +find_library(FOUNDATION_LIBRARY Foundation REQUIRED) +find_library(COCOA_LIBRARY Cocoa REQUIRED) +find_library(APPKIT_LIBRARY AppKit REQUIRED) string(TIMESTAMP VERSION_YEAR "%Y") set(MACOSX_BUNDLE_INFO_STRING "MacFreeRDP") @@ -27,102 +23,76 @@ set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2013-${VERSION_YEAR}. All Rights Reserved set(MACOSX_BUNDLE_NSMAIN_NIB_FILE "MainMenu") set(MACOSX_BUNDLE_NSPRINCIPAL_CLASS "NSApplication") -mark_as_advanced(COCOA_LIBRARY FOUNDATION_LIBRARY APPKIT_LIBRARY) -set(APP_TYPE MACOSX_BUNDLE) +set(XIBS MainMenu.xib) -set(${MODULE_PREFIX}_XIBS MainMenu.xib) +set(SOURCES "") -set(${MODULE_PREFIX}_SOURCES "") - -set(${MODULE_PREFIX}_OBJECTIVE_SOURCES +set(OBJECTIVE_SOURCES main.m - AppDelegate.m) + AppDelegate.m + ) -list(APPEND ${MODULE_PREFIX}_SOURCES ${${MODULE_PREFIX}_OBJECTIVE_SOURCES}) +list(APPEND SOURCES ${OBJECTIVE_SOURCES}) -set(${MODULE_PREFIX}_HEADERS - AppDelegate.h) - -set(${MODULE_PREFIX}_RESOURCES ${MACOSX_BUNDLE_ICON_FILE}) +set(HEADERS + AppDelegate.h + ) +set(RESOURCES + "en.lproj/InfoPlist.strings" + ${MACOSX_BUNDLE_ICON_FILE} +) # Include XIB file in Xcode resources. if("${CMAKE_GENERATOR}" MATCHES "Xcode") - message(STATUS "Adding Xcode XIB resources for ${MODULE_NAME}") - set(${MODULE_PREFIX}_RESOURCES ${${MODULE_PREFIX}_RESOURCES} ${${MODULE_PREFIX}_XIBS}) + message(STATUS "Adding Xcode XIB resources for ${MODULE_NAME}") + list(APPEND RESOURCES ${XIBS}) + set(IS_XCODE ON) endif() -add_executable(${MODULE_NAME} - ${APP_TYPE} - ${${MODULE_PREFIX}_HEADERS} - ${${MODULE_PREFIX}_SOURCES} - ${${MODULE_PREFIX}_RESOURCES}) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in ${CMAKE_CURRENT_BINARY_DIR}/Info.plist @ONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/PkgInfo.in ${CMAKE_CURRENT_BINARY_DIR}/PkgInfo @ONLY) -set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "${MODULE_OUTPUT_NAME}") -add_dependencies(${MODULE_NAME} prepare-framework-headers) +add_executable(${PROJECT_NAME} + ${HEADERS} + ${SOURCES} + ${RESOURCES}) -# This is necessary for the xib file part below -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Info.plist ${CMAKE_CURRENT_BINARY_DIR}/Info.plist) +set_target_properties(${PROJECT_NAME} PROPERTIES RESOURCE "${RESOURCES}") +set_target_properties(${PROJECT_NAME} PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist) -# This allows for automatic xib to nib ibitool -set_target_properties(${MODULE_NAME} PROPERTIES RESOURCE "${${MODULE_PREFIX}_RESOURCES}") +target_link_libraries(${PROJECT_NAME} PRIVATE + ${COCOA_LIBRARY} + ${FOUNDATION_LIBRARY} + ${APPKIT_LIBRARY} + MacFreeRDP-library + ) -# Tell the compiler where to look for the FreeRDP framework -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -F../") -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -F../") +if (NOT IS_XCODE) + find_program(IBTOOL ibtool REQUIRED + HINTS + "/usr/bin" + "${OSX_DEVELOPER_ROOT}/usr/bin" + ) -if(CMAKE_GENERATOR MATCHES "Ninja") - if (NOT ${CONFIGURATION} STREQUAL "") - set(safe_configuration "$CONFIGURATION") - else() - set(safe_configuration "") - endif() -else() - set(safe_configuration "$(CONFIGURATION)") + # Compile the .xib files using the 'ibtool' program with the destination being the app package + + foreach(xib ${XIBS}) + get_filename_component(XIB_WE ${xib} NAME_WE) + set(NIB ${CMAKE_CURRENT_BINARY_DIR}/${XIB_WE}.nib) + list(APPEND NIBS ${NIB}) + + add_custom_command (TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${IBTOOL} --errors --warnings --notices --output-format human-readable-text + --compile ${NIB} ${CMAKE_CURRENT_SOURCE_DIR}/${xib} + COMMENT "Compiling ${xib}") + endforeach() + + install(FILES ${NIBS} DESTINATION ${CMAKE_INSTALL_DATADIR}) endif() -# Tell XCode where to look for the MacFreeRDP framework -set_target_properties(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS - "${XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS} ${CMAKE_CURRENT_BINARY_DIR}/../${safe_configuration}") - -# Set the info plist to the custom instance -set_target_properties(${MODULE_NAME} PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist) - -# Disable transitive linking -target_link_libraries(${MODULE_NAME} ${COCOA_LIBRARY} ${FOUNDATION_LIBRARY} ${APPKIT_LIBRARY} MacFreeRDP-library) - -set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Client/Mac") - -# Embed the FreeRDP framework into the app bundle -add_custom_command(TARGET ${MODULE_NAME} POST_BUILD - COMMAND mkdir ARGS -p ${CMAKE_CURRENT_BINARY_DIR}/${safe_configuration}/${MODULE_OUTPUT_NAME}.app/Contents/Frameworks - COMMAND ditto ${CMAKE_CURRENT_BINARY_DIR}/../${safe_configuration}/MacFreeRDP.framework ${CMAKE_CURRENT_BINARY_DIR}/${safe_configuration}/${MODULE_OUTPUT_NAME}.app/Contents/Frameworks/MacFreeRDP.framework - COMMAND install_name_tool -change "@executable_path/../Frameworks/MacFreeRDP.framework/Versions/${MAC_OS_X_BUNDLE_BUNDLE_VERSION}/MacFreeRDP" - "@executable_path/../Frameworks/MacFreeRDP.framework/Versions/Current/MacFreeRDP" - "${CMAKE_CURRENT_BINARY_DIR}/${safe_configuration}/${MODULE_OUTPUT_NAME}.app/Contents/MacOS/${MODULE_NAME}" - COMMENT Setting install name for MacFreeRDP) - -# Add post-build NIB file generation in unix makefiles. XCode handles this implicitly. -if(NOT "${CMAKE_GENERATOR}" MATCHES "Xcode") - message(STATUS "Adding post-build NIB file generation event for ${MODULE_NAME}") - - # Make sure we can find the 'ibtool' program. If we can NOT find it we skip generation of this project - find_program(IBTOOL ibtool HINTS "/usr/bin" "${OSX_DEVELOPER_ROOT}/usr/bin") - if (${IBTOOL} STREQUAL "IBTOOL-NOTFOUND") - message(SEND_ERROR "ibtool can not be found and is needed to compile the .xib files. It should have been installed with - the Apple developer tools. The default system paths were searched in addition to ${OSX_DEVELOPER_ROOT}/usr/bin") - endif() - - # Make sure the 'Resources' Directory is correctly created before we build - add_custom_command(TARGET ${MODULE_NAME} PRE_BUILD COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/${safe_configuration}/${MODULE_OUTPUT_NAME}.app/Contents/Resources) - - # Compile the .xib files using the 'ibtool' program with the destination being the app package - foreach(xib ${${MODULE_PREFIX}_XIBS}) - get_filename_component(XIB_WE ${xib} NAME_WE) - - add_custom_command (TARGET ${MODULE_NAME} POST_BUILD - COMMAND ${IBTOOL} --errors --warnings --notices --output-format human-readable-text - --compile ${CMAKE_CURRENT_BINARY_DIR}/${safe_configuration}/${MODULE_OUTPUT_NAME}.app/Contents/Resources/${XIB_WE}.nib ${CMAKE_CURRENT_SOURCE_DIR}/${xib} - COMMENT "Compiling ${xib}") - endforeach() - -endif() +install(TARGETS ${PROJECT_NAME} + COMPONENT client + RESOURCE DESTINATION ${CMAKE_INSTALL_DATADIR} + ) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Info.plist DESTINATION ${CMAKE_INSTALL_PREFIX}) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/PkgInfo DESTINATION ${CMAKE_INSTALL_PREFIX}) diff --git a/client/Mac/cli/Info.plist b/client/Mac/cli/Info.plist.in similarity index 100% rename from client/Mac/cli/Info.plist rename to client/Mac/cli/Info.plist.in diff --git a/client/Mac/cli/PkgInfo.in b/client/Mac/cli/PkgInfo.in new file mode 100644 index 000000000..bd04210fb --- /dev/null +++ b/client/Mac/cli/PkgInfo.in @@ -0,0 +1 @@ +APPL???? \ No newline at end of file diff --git a/cmake/ConfigureRPATH.cmake b/cmake/ConfigureRPATH.cmake index 97eaea0ef..9af2af8f3 100644 --- a/cmake/ConfigureRPATH.cmake +++ b/cmake/ConfigureRPATH.cmake @@ -3,7 +3,8 @@ set(CMAKE_SKIP_BUILD_RPATH FALSE) set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE) if (APPLE) - set(CMAKE_INSTALL_RPATH "@loader_path/../Frameworks") + file(RELATIVE_PATH FRAMEWORK_PATH ${CMAKE_INSTALL_FULL_BINDIR} ${CMAKE_INSTALL_FULL_LIBDIR}) + set(CMAKE_INSTALL_RPATH "@loader_path/${FRAMEWORK_PATH}") else (APPLE) if (NOT FREEBSD) set(CMAKE_INSTALL_RPATH "\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}:\$ORIGIN/..") diff --git a/scripts/bundle-mac-os.sh b/scripts/bundle-mac-os.sh new file mode 100755 index 000000000..f24bb028b --- /dev/null +++ b/scripts/bundle-mac-os.sh @@ -0,0 +1,134 @@ +#!/bin/bash -xe +SCRIPT_PATH="$(dirname -- "${BASH_SOURCE[0]}")" # relative +SCRIPT_PATH="$(cd -- "$SCRIPT_PATH" && pwd)" # absolutized and normalized + +BASE=$(pwd) +SRC="$BASE/src" +BUILD="$BASE/build" +INSTALL="$BASE/install/MacFreeRDP.app/Contents" + +BINDIR=MacOS +LIBDIR=Frameworks +DATADIR=Resources + +OSSL_FLAGS="-arch arm64 -arch x86_64" + +CMAKE_ARGS="-DCMAKE_SKIP_INSTALL_ALL_DEPENDENCY=ON \ + -DCMAKE_VERBOSE_MAKEFILE=ON \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_SHARED_LIBS=ON \ + -DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=12 \ + -DCMAKE_INSTALL_PREFIX='$INSTALL' \ + -DCMAKE_INSTALL_LIBDIR='$LIBDIR' \ + -DCMAKE_INSTALL_BINDIR='$BINDIR' \ + -DCMAKE_INSTALL_DATADIR='$DATADIR' \ + -DINSTALL_LIB_DIR='$INSTALL/$LIBDIR' \ + -DINSTALL_BIN_DIR='$INSTALL/$BINDIR' \ + -DCMAKE_PREFIX_PATH='$INSTALL;$INSTALL/$LIBDIR;$INSTALL/$LIBDIR/cmake' \ + -DCMAKE_IGNORE_PATH='/opt/local;/usr/local;/opt/homebrew' + " + +if [ ! -d $SRC ]; +then + mkdir -p $SRC + cd $SRC + git clone -b openssl-3.2.0 https://github.com/openssl/openssl.git + git clone --depth 1 -b v1.3 https://github.com/madler/zlib.git + git clone --depth 1 -b uriparser-0.9.7 https://github.com/uriparser/uriparser.git + git clone --depth 1 -b v1.7.16 https://github.com/DaveGamble/cJSON.git + git clone --depth 1 -b release-2.28.1 https://github.com/libsdl-org/SDL.git + git clone --depth 1 --shallow-submodules --recurse-submodules -b release-2.20.2 https://github.com/libsdl-org/SDL_ttf.git + git clone --depth 1 --shallow-submodules --recurse-submodules -b v1.0.26 https://github.com/libusb/libusb-cmake.git + git clone --depth 1 -b n6.0 https://github.com/FFmpeg/FFmpeg.git + git clone --depth 1 -b v2.4.0 https://github.com/cisco/openh264.git +fi + +if [ -d $INSTALL ]; +then + rm -rf $INSTALL +fi + +if [ -d $BUILD ]; +then + rm -rf $BUILD +fi + +mkdir -p $BUILD +cd $BUILD + +cmake -GNinja -Bzlib -S$SRC/zlib $CMAKE_ARGS +cmake --build zlib +cmake --install zlib + +cmake -GNinja -Buriparser -S$SRC/uriparser $CMAKE_ARGS -DURIPARSER_BUILD_DOCS=OFF -DURIPARSER_BUILD_TESTS=OFF +cmake --build uriparser +cmake --install uriparser + +cmake -GNinja -BcJSON -S$SRC/cJSON $CMAKE_ARGS -DENABLE_CJSON_TEST=OFF -DBUILD_SHARED_AND_STATIC_LIBS=OFF +cmake --build cJSON +cmake --install cJSON + +cmake -GNinja -BSDL -S$SRC/SDL $CMAKE_ARGS -DSDL_TEST=OFF -DSDL_TESTS=OFF -DSDL_STATIC_PIC=ON +cmake --build SDL +cmake --install SDL + +cmake -GNinja -BSDL_ttf -S$SRC/SDL_ttf $CMAKE_ARGS -DSDL2TTF_HARFBUZZ=ON -DSDL2TTF_FREETYPE=ON -DSDL2TTF_VENDORED=ON \ + -DFT_DISABLE_ZLIB=OFF -DSDL2TTF_SAMPLES=OFF +cmake --build SDL_ttf +cmake --install SDL_ttf + +cmake -GNinja -Blibusb-cmake -S$SRC/libusb-cmake $CMAKE_ARGS -DLIBUSB_BUILD_EXAMPLES=OFF -DLIBUSB_BUILD_TESTING=OFF \ + -DLIBUSB_ENABLE_DEBUG_LOGGING=OFF -DLIBUSB_BUILD_SHARED_LIBS=ON +cmake --build libusb-cmake +cmake --install libusb-cmake + +mkdir -p openssl +cd openssl + +CFLAGS=$OSSL_FLAGS LDFLAGS=$OSSL_FLAGS $SRC/openssl/config --prefix=$INSTALL --libdir=$LIBDIR no-asm no-tests no-docs no-apps zlib +CFLAGS=$OSSL_FLAGS LDFLAGS=$OSSL_FLAGS make -j build_sw +CFLAGS=$OSSL_FLAGS LDFLAGS=$OSSL_FLAGS make -j install_sw + +cd $BUILD + +meson setup --prefix="$INSTALL" -Doptimization=3 -Db_lto=true -Db_pie=true -Dc_args="$OSSL_FLAGS" -Dc_link_args="$OSSL_FLAGS" \ + -Dcpp_args="$OSSL_FLAGS" -Dcpp_link_args="$OSSL_FLAGS" -Dpkgconfig.relocatable=true -Dtests=disabled -Dbindir=$BINDIR \ + -Dlibdir=$LIBDIR openh264 $SRC/openh264 +ninja -C openh264 install + +cmake -GNinja -Bfreerdp -S"$SCRIPT_PATH/.." $CMAKE_ARGS -DWITH_PLATFORM_SERVER=OFF -DWITH_NEON=OFF -DWITH_SSE=OFF -DWITH_FFMPEG=OFF \ + -DWITH_SWSCALE=OFF -DWITH_OPUS=OFF -DWITH_WEBVIEW=OFF +cmake --build freerdp +cmake --install freerdp + +# some build systems do not handle @rpath on mac os correctly. +# do check that and fix it. +DYLIB_ABS_NAMES=$(find $INSTALL/$LIBDIR -name "*.dylib") +for DYLIB_ABS in $DYLIB_ABS_NAMES; +do + DYLIB_NAME=$(basename $DYLIB_ABS) + install_name_tool -id @rpath/$DYLIB_NAME $DYLIB_ABS + + for DYLIB_DEP in $(otool -L $DYLIB_ABS | grep "$INSTALL/$LIBDIR" | cut -d' ' -f1); + do + if [[ $DYLIB_DEP == $DYLIB_ABS ]]; + then + continue + elif [[ $DYLIB_DEP == $INSTALL/$LIBDIR/* ]]; + then + DEP_BASE=$(basename $DYLIB_DEP) + install_name_tool -change $DYLIB_DEP @rpath/$DEP_BASE $DYLIB_ABS + fi + done +done + +# clean up unused data +rm -rf "$INSTALL/include" +rm -rf "$INSTALL/share" +rm -rf "$INSTALL/bin" +rm -rf "$INSTALL/$LIBDIR/cmake" +rm -rf "$INSTALL/$LIBDIR/pkgconfig" +rm -f "$INSTALL/$LIBDIR/*.a" + +# TODO: Create remaining files required