How to get the target(s) for a PBXFileReference in Xcodeproj - ruby

I'm attempting to write a Ruby script that will delete certain files from the Xcode project. I can find the files based on the absolute path and remove them from the project using the remove_from_project method of PBXFileReference. However this leaves source files (e.g. .m or .swift files) in the "Compile Sources" build phase of whatever target(s) it is a member of, but without a name.
I know I need to also remove the file from the target(s) but there seems to be no easy link between a PBXFileReference and a target (PBXNativeTarget).
From what I can make out I need to iterate through each of the project's targets, then iterate through the files or files_references of that target's source_build_phase looking for the PBXFileReference I already have.
Is this correct or am I missing some obvious link such e.g. file_ref.target_memberships?

if (object.is_a?(Xcodeproj::Project::Object::PBXFileReference))
if (!object.real_path.exist?)
object.remove_from_project
end
end
project.save(project_path)

Not sure when this was introduced, but as of xcodeproj version 1.15.0, you can can get the build files associated with a file reference with:
file_ref.build_files
From the documentation:
Method: Xcodeproj::Project::Object::PBXFileReference#build_files
#build_files ⇒ Array<PBXBuildFile>
Returns the build files associated with the current file reference.
Returns:
(Array<PBXBuildFile>) — the build files associated with the current file reference.
Seems like this should do the trick:
file_ref.build_files.each { |file| file.remove_from_project }

Related

RTD compiles all my docs including foreign docs from git submodules

I'm experimenting with Sphinx and ReadTheDocs (RTD) to compile my documentation on every GitHub push. Unfortunately, RTD found multiple doc/docs folders containing a conf.py file.
My repository uses git sub-modules to embed third party libraries. Some of them are also documented using Sphinx. I assume the biggest (long lasting documentation build) wins and overwrites all static HTML pages in the final RTD view.
How can I exclude or tell RTD to ignore the folders of these sub-modules:
lib/cocotb
lib/osvvm
lib/vunit
docs/source/_themes/sphinx_rtd_theme
My documentation is located here:
docs/source/conf.py
docs/source/index.rst
As far as I have found, RTD does support *.yml files, but there is no entry to define the documentation root folder.
Any ideas to solve my problem?
Inside conf.py, there is a list that looks like this
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = []
You can put the files you want to ignore inside it like
exclude_patterns = ["lib/cocotb", "lib/osvvm", "lib/vunit", "docs/_themes/sphinx_rtd_theme"]
Please note that here the pattern is relative to the source directory, you can put / at the beginning of each file pattern above to make this more clear.
The main documentation folder and its conf.py can be configured in the Advanced Settings tab in the per project settings.
Example value: documentation/conf.py

force object files in current directory even when subdir-objects is on

I have 2 libraries that share same source files:
# src/lib_mt/Makefile.am:
libppb_la_SOURCES = rphs_mt.c timer_mt.c
# src/sipplib/Makefile.am:
libsipp_a_SOURCES = ../lib_mt/rphs_mt.c ../lib_mt/timer_mt.c
Each source file compiled twice. First for lib_mt with -fPIC, second for sipplib without -fPIC.
Object files for each library created in corresponding directory.
Eventually subdir-objects becomes default. How to keep current behavior for these 2 source files? Some explicit rule maybe?
There is no way to disable that the moment it becomes the default. What you can do instead is migrate this to a non-recursive Automake buildsystem. At that point, it will know that there are different targets compiling the same source files with different flags (it requires AC_PROG_CC_C_O to be called in configure.ac.)
Alternatively, the hacky version is to create a src/sipplib/rphs_mt.c file that only contains
#include "../libmt/rphs_mt.c"
so that it is actually a separate build target.

cmake: add_custom_command only invoked first time

I'm running into a problem with add_custom_command for a custom target (created using add_custom_target).
My general idea is to incorporate a static code analysis tool into the cmake tool-chain. My solution is based on the one described here: https://github.com/rpavlik/cmake-modules/blob/master/CppcheckTargets.cmake
In a nutshell, each project that I want to run static code analysis for has the following two lines of code:
include(cppcheck)
add_cppcheck(${le_project} STYLE POSSIBLE_ERROR FAIL_ON_WARNINGS)
The module has this at the top of the file:
if (NOT TARGET ANALYZE_CODE)
add_custom_target(ANALYZE_CODE WORKING_DIRECTORY ${LE_LITEN_ROOT})
set_target_properties(ANALYZE_CODE PROPERTIES EXCLUDE_FROM_ALL TRUE)
endif ()
and later on in the function the custom command is added:
add_custom_command(TARGET
ANALYZE_CODE
PRE_BUILD
COMMAND
${CPPCHECK_EXECUTABLE}
${CPPCHECK_QUIET_ARG}
${CPPCHECK_TEMPLATE_ARG}
${_cppcheck_args}
${_files}
WORKING_DIRECTORY
"${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT
"${_name}_cppcheck: Running cppcheck on target ${_name}..."
VERBATIM)
The problem I'm seeing is that the command is only added for the project that included the file first. I'm not sure why and what is going on. I verified the following using message() commands:
The target is only created once
The add_custom_command is run for every project that calls the function, with proper arguments
But when I actually look at the target in visual studio, only the first include / function call command is added.
If the file is only included without calling the function, no custom commands are added at all.
Desired behavior:
I would like ONE target named "ANALYZE_CODE" to run all commands added by calls to the function.
I.e. if 3 projects include the two lines from above, the target ANALYZE_CODE is created once but 3 custom commands are added to it, one for each project.
It turns out you're somewhat stuck between a rock and a hard place here. The issue I think boils down to a couple of factors.
Firstly, although the docs don't make it clear, add_custom_command(TARGET ...) only works for targets created in the same directory. So the first subproject to call include(cppcheck) is the only one which can effectively add custom commands to the target ANALYZE_CODE.
A workaround for this might seem to be to move all calls to add_cppcheck from their respective subdirectories up to the top-level CMakeLists file.
include(cppcheck)
add_cppcheck(${le_first_project} STYLE POSSIBLE_ERROR FAIL_ON_WARNINGS)
add_cppcheck(${le_second_project} STYLE POSSIBLE_ERROR FAIL_ON_WARNINGS)
...
This isn't a great solution, since these really belong inside their own subdirs. But a bigger issue is that properties on source files only persist in the scope of the CMakeLists.txt in which they are added. This isn't obvious at all, but from the docs for set_source_files_properties:
Source file properties are visible only to targets added in the same directory (CMakeLists.txt).
The innards of the add_cppcheck have the following block of code:
foreach(_source ${_cppcheck_sources})
get_source_file_property(_cppcheck_lang "${_source}" LANGUAGE)
get_source_file_property(_cppcheck_loc "${_source}" LOCATION)
if("${_cppcheck_lang}" MATCHES "CXX")
list(APPEND _files "${_cppcheck_loc}")
endif()
endforeach()
So this is checking that each source file for the given target is designated as a C++ file before adding it to the list of files to be given to cppcheck. If this function is invoked from within the CMakeLists.txt where the target is defined (i.e. the subdir) then the files all have the appropriate property and are correctly added.
However, if the function is called from the parent CMakeLists.txt, the files have lost their properties, and so none are added and cppcheck is passed an empty list!
Now for the possible fixes. There are probably few ways to get out of this hole - I can point to a couple.
You could continue with the option to always call add_cppcheck from the top-level CMake file and avoid using the source files' properties. So the problem codeblock above could be changed to something more like:
set(CxxExtensions .cpp .CPP .cc .CC .cxx .CXX)
foreach(_source ${_cppcheck_sources})
get_filename_component(Extension "${_source}" EXT)
list(FIND CxxExtensions "${Extension}" IsCxxFile)
if(IsCxxFile GREATER -1)
list(APPEND _files "${_source}")
endif()
endforeach()
You could even enforce that the function is only called from the top-level CMakeLists.txt by adding something like this at the start of the function:
if(NOT "${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
message(FATAL_ERROR "This can only be called from the top-level CMakeLists.txt")
endif()
The second fix (which I'd personally favour) is to leave the add_cppcheck calls inside the subdirs and have the function add a custom target rather than command. These targets can successfully be applied as dependencies of the top-level target ANALYZE_CODE. So for example, change the add_custom_command to something like:
add_custom_target(ANALYZE_${_name}
${CPPCHECK_EXECUTABLE}
${CPPCHECK_QUIET_ARG}
${CPPCHECK_TEMPLATE_ARG}
${_cppcheck_args}
${_files}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "ANALYZE_${_name}: Running cppcheck on target ${_name}..."
VERBATIM)
add_dependencies(ANALYZE_CODE ANALYZE_${_name})
set_target_properties(ANALYZE_${_name} PROPERTIES FOLDER "Code Analysis")
This should cause building ANALYZE_CODE to trigger building each of the subordinate ANALYZE_... targets.
It has the downside of "polluting" the solution with a lot of extra targets, but an upside is that you could use these targets in the add_test calls (although this may be a step too far):
# CMake 2.8.0 and newer
add_test(NAME ${_name}_cppcheck_test
COMMAND ${CMAKE_COMMAND}
--build ${CMAKE_BINARY_DIR}
--target ANALYZE_${_name})

Windows Compact Embedded - Include external native files

I have created a Sub project which just prints "Hello World". My goal is to create a C file inside the same subproject but within a folder named "src", also I want to create a H file within a folder named "include".
The H file contains only one function declaration "void printContent();" and the C file contains its definition which prints "Hello Buddy".
I added the C file inside the Source Files section of Sub project and added the H file inside the Header File Section, but when I compile the subproject and try to deploy it on to an emulator, I got an error.
BUILD: [01:0000000047:ERRORE] NMAKE : U1073: don't know how to make 'obj\ARMV4I\debug\content.obj'
I tried to configure the subproject by providing the below lines in the sources file of every Sub project.
INCLUDES= include/
But nothing changed and the problem still persists.
In wince subproject, sub folders are treated differently in the source file layout.
Rule No.1 You can't have both source and dirs files in the same folder.
So you either use one folder, or use several sub folders, then the root folder is clean and have one dirs file and several folders, no source file.
Rule No. 2 Each sub folder should have both source and makefile
You can copy and then edit the source file, the makefile will always be the same.
Ok, if you are going to use subfolder just to make the folder structure cleaner, my suggestion is that you create 2 subprojects, one is the main subproject; the other includes all your src files and its type is set to be static library. Then you can link to the static .lib file just as you are including them as in a subfolder. Of cource you need to set the additional include folder and input library.

Previous definition is here - Ghost File in XCode 4.2.1

I'm getting a compile error in XCode where a file that I've removed from the project is showing up as a Duplicate Interface definition for class 'class_name' and it shows the hierarchy of dependencies and ultimately arrives at the header file of the class in question. But that header file doesn't actually exist in the project hierarchy. In the file location section above the header file's code it just shows class_name.h > #interface class_name rather than every other file in the project: project_name > group_name > class_name.h > No Selection
Doing a search for this object type (cmd+shift+O) and global search turn up no instance of this header file existing in the project. I've cleaned, exited xcode, rebooted, even checked the proj file for instances of this class, but it's not there.
I had the path to the old location of my class in my project's "Header Search Paths" so it was seeing the file twice.
First step: properly manage your xcode Header Search Path, delete the unused old Search path
Second step: choose product-->clean

Resources