mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-24 14:49:42 -06:00
Merge pull request #11103 from JosJuice/android-gamefilecache-not-null
Android: Allocate GameFileCache on GUI thread
This commit is contained in:
@ -74,7 +74,7 @@ public class AppLinkActivity extends FragmentActivity
|
|||||||
});
|
});
|
||||||
|
|
||||||
DirectoryInitialization.start(this);
|
DirectoryInitialization.start(this);
|
||||||
GameFileCacheManager.startLoad(this);
|
GameFileCacheManager.startLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -233,7 +233,7 @@ public class Settings implements Closeable
|
|||||||
if (mLoadedRecursiveIsoPathsValue != BooleanSetting.MAIN_RECURSIVE_ISO_PATHS.getBoolean(this))
|
if (mLoadedRecursiveIsoPathsValue != BooleanSetting.MAIN_RECURSIVE_ISO_PATHS.getBoolean(this))
|
||||||
{
|
{
|
||||||
// Refresh game library
|
// Refresh game library
|
||||||
GameFileCacheManager.startRescan(context);
|
GameFileCacheManager.startRescan();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -109,11 +109,11 @@ public class GameFileCache
|
|||||||
|
|
||||||
public static native String[] getAllGamePaths(String[] folderPaths, boolean recursiveScan);
|
public static native String[] getAllGamePaths(String[] folderPaths, boolean recursiveScan);
|
||||||
|
|
||||||
public native int getSize();
|
public synchronized native int getSize();
|
||||||
|
|
||||||
public native GameFile[] getAllGames();
|
public synchronized native GameFile[] getAllGames();
|
||||||
|
|
||||||
public native GameFile addOrGet(String gamePath);
|
public synchronized native GameFile addOrGet(String gamePath);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the list of games to cache.
|
* Sets the list of games to cache.
|
||||||
@ -123,7 +123,7 @@ public class GameFileCache
|
|||||||
*
|
*
|
||||||
* @return true if the cache was modified
|
* @return true if the cache was modified
|
||||||
*/
|
*/
|
||||||
public native boolean update(String[] gamePaths);
|
public synchronized native boolean update(String[] gamePaths);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For each game that already is in the cache, scans the folder that contains the game
|
* For each game that already is in the cache, scans the folder that contains the game
|
||||||
@ -131,9 +131,9 @@ public class GameFileCache
|
|||||||
*
|
*
|
||||||
* @return true if the cache was modified
|
* @return true if the cache was modified
|
||||||
*/
|
*/
|
||||||
public native boolean updateAdditionalMetadata();
|
public synchronized native boolean updateAdditionalMetadata();
|
||||||
|
|
||||||
public native boolean load();
|
public synchronized native boolean load();
|
||||||
|
|
||||||
public native boolean save();
|
public synchronized native boolean save();
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
package org.dolphinemu.dolphinemu.services;
|
package org.dolphinemu.dolphinemu.services;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
@ -23,14 +21,15 @@ import java.util.concurrent.Executors;
|
|||||||
*/
|
*/
|
||||||
public final class GameFileCacheManager
|
public final class GameFileCacheManager
|
||||||
{
|
{
|
||||||
private static GameFileCache gameFileCache = null;
|
private static GameFileCache sGameFileCache = null;
|
||||||
private static final MutableLiveData<GameFile[]> gameFiles =
|
private static final MutableLiveData<GameFile[]> sGameFiles =
|
||||||
new MutableLiveData<>(new GameFile[]{});
|
new MutableLiveData<>(new GameFile[]{});
|
||||||
private static boolean runRescanAfterLoad = false;
|
private static boolean sFirstLoadDone = false;
|
||||||
|
private static boolean sRunRescanAfterLoad = false;
|
||||||
|
|
||||||
private static final ExecutorService executor = Executors.newFixedThreadPool(1);
|
private static final ExecutorService sExecutor = Executors.newFixedThreadPool(1);
|
||||||
private static final MutableLiveData<Boolean> loadInProgress = new MutableLiveData<>(false);
|
private static final MutableLiveData<Boolean> sLoadInProgress = new MutableLiveData<>(false);
|
||||||
private static final MutableLiveData<Boolean> rescanInProgress = new MutableLiveData<>(false);
|
private static final MutableLiveData<Boolean> sRescanInProgress = new MutableLiveData<>(false);
|
||||||
|
|
||||||
private GameFileCacheManager()
|
private GameFileCacheManager()
|
||||||
{
|
{
|
||||||
@ -38,12 +37,12 @@ public final class GameFileCacheManager
|
|||||||
|
|
||||||
public static LiveData<GameFile[]> getGameFiles()
|
public static LiveData<GameFile[]> getGameFiles()
|
||||||
{
|
{
|
||||||
return gameFiles;
|
return sGameFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<GameFile> getGameFilesForPlatform(Platform platform)
|
public static List<GameFile> getGameFilesForPlatform(Platform platform)
|
||||||
{
|
{
|
||||||
GameFile[] allGames = gameFiles.getValue();
|
GameFile[] allGames = sGameFiles.getValue();
|
||||||
ArrayList<GameFile> platformGames = new ArrayList<>();
|
ArrayList<GameFile> platformGames = new ArrayList<>();
|
||||||
for (GameFile game : allGames)
|
for (GameFile game : allGames)
|
||||||
{
|
{
|
||||||
@ -57,7 +56,7 @@ public final class GameFileCacheManager
|
|||||||
|
|
||||||
public static GameFile getGameFileByGameId(String gameId)
|
public static GameFile getGameFileByGameId(String gameId)
|
||||||
{
|
{
|
||||||
GameFile[] allGames = gameFiles.getValue();
|
GameFile[] allGames = sGameFiles.getValue();
|
||||||
for (GameFile game : allGames)
|
for (GameFile game : allGames)
|
||||||
{
|
{
|
||||||
if (game.getGameId().equals(gameId))
|
if (game.getGameId().equals(gameId))
|
||||||
@ -72,7 +71,7 @@ public final class GameFileCacheManager
|
|||||||
{
|
{
|
||||||
GameFile matchWithoutRevision = null;
|
GameFile matchWithoutRevision = null;
|
||||||
|
|
||||||
GameFile[] allGames = gameFiles.getValue();
|
GameFile[] allGames = sGameFiles.getValue();
|
||||||
for (GameFile otherGame : allGames)
|
for (GameFile otherGame : allGames)
|
||||||
{
|
{
|
||||||
if (game.getGameId().equals(otherGame.getGameId()) &&
|
if (game.getGameId().equals(otherGame.getGameId()) &&
|
||||||
@ -102,7 +101,7 @@ public final class GameFileCacheManager
|
|||||||
*/
|
*/
|
||||||
public static LiveData<Boolean> isLoading()
|
public static LiveData<Boolean> isLoading()
|
||||||
{
|
{
|
||||||
return loadInProgress;
|
return sLoadInProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -110,12 +109,12 @@ public final class GameFileCacheManager
|
|||||||
*/
|
*/
|
||||||
public static LiveData<Boolean> isRescanning()
|
public static LiveData<Boolean> isRescanning()
|
||||||
{
|
{
|
||||||
return rescanInProgress;
|
return sRescanInProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isLoadingOrRescanning()
|
public static boolean isLoadingOrRescanning()
|
||||||
{
|
{
|
||||||
return loadInProgress.getValue() || rescanInProgress.getValue();
|
return sLoadInProgress.getValue() || sRescanInProgress.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -123,13 +122,15 @@ public final class GameFileCacheManager
|
|||||||
* if the games are still present in the user's configured folders.
|
* if the games are still present in the user's configured folders.
|
||||||
* If this has already been called, calling it again has no effect.
|
* If this has already been called, calling it again has no effect.
|
||||||
*/
|
*/
|
||||||
public static void startLoad(Context context)
|
public static void startLoad()
|
||||||
{
|
{
|
||||||
if (!loadInProgress.getValue())
|
createGameFileCacheIfNeeded();
|
||||||
|
|
||||||
|
if (!sLoadInProgress.getValue())
|
||||||
{
|
{
|
||||||
loadInProgress.setValue(true);
|
sLoadInProgress.setValue(true);
|
||||||
new AfterDirectoryInitializationRunner().runWithoutLifecycle(
|
new AfterDirectoryInitializationRunner().runWithoutLifecycle(
|
||||||
() -> executor.execute(GameFileCacheManager::load));
|
() -> sExecutor.execute(GameFileCacheManager::load));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,13 +140,15 @@ public final class GameFileCacheManager
|
|||||||
* If loading the game file cache hasn't started or hasn't finished,
|
* If loading the game file cache hasn't started or hasn't finished,
|
||||||
* the execution of this will be postponed until it finishes.
|
* the execution of this will be postponed until it finishes.
|
||||||
*/
|
*/
|
||||||
public static void startRescan(Context context)
|
public static void startRescan()
|
||||||
{
|
{
|
||||||
if (!rescanInProgress.getValue())
|
createGameFileCacheIfNeeded();
|
||||||
|
|
||||||
|
if (!sRescanInProgress.getValue())
|
||||||
{
|
{
|
||||||
rescanInProgress.setValue(true);
|
sRescanInProgress.setValue(true);
|
||||||
new AfterDirectoryInitializationRunner().runWithoutLifecycle(
|
new AfterDirectoryInitializationRunner().runWithoutLifecycle(
|
||||||
() -> executor.execute(GameFileCacheManager::rescan));
|
() -> sExecutor.execute(GameFileCacheManager::rescan));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,8 +156,8 @@ public final class GameFileCacheManager
|
|||||||
{
|
{
|
||||||
// Common case: The game is in the cache, so just grab it from there.
|
// Common case: The game is in the cache, so just grab it from there.
|
||||||
// (Actually, addOrGet already checks for this case, but we want to avoid calling it if possible
|
// (Actually, addOrGet already checks for this case, but we want to avoid calling it if possible
|
||||||
// because onHandleIntent may hold a lock on gameFileCache for extended periods of time.)
|
// because the executor thread may hold a lock on sGameFileCache for extended periods of time.)
|
||||||
GameFile[] allGames = gameFiles.getValue();
|
GameFile[] allGames = sGameFiles.getValue();
|
||||||
for (GameFile game : allGames)
|
for (GameFile game : allGames)
|
||||||
{
|
{
|
||||||
if (game.getPath().equals(gamePath))
|
if (game.getPath().equals(gamePath))
|
||||||
@ -165,10 +168,8 @@ public final class GameFileCacheManager
|
|||||||
|
|
||||||
// Unusual case: The game wasn't found in the cache.
|
// Unusual case: The game wasn't found in the cache.
|
||||||
// Scan the game and add it to the cache so that we can return it.
|
// Scan the game and add it to the cache so that we can return it.
|
||||||
synchronized (gameFileCache)
|
createGameFileCacheIfNeeded();
|
||||||
{
|
return sGameFileCache.addOrGet(gamePath);
|
||||||
return gameFileCache.addOrGet(gamePath);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -178,30 +179,26 @@ public final class GameFileCacheManager
|
|||||||
*/
|
*/
|
||||||
private static void load()
|
private static void load()
|
||||||
{
|
{
|
||||||
if (gameFileCache == null)
|
if (!sFirstLoadDone)
|
||||||
{
|
{
|
||||||
GameFileCache temp = new GameFileCache();
|
sFirstLoadDone = true;
|
||||||
synchronized (temp)
|
sGameFileCache.load();
|
||||||
|
if (sGameFileCache.getSize() != 0)
|
||||||
{
|
{
|
||||||
gameFileCache = temp;
|
updateGameFileArray();
|
||||||
gameFileCache.load();
|
|
||||||
if (gameFileCache.getSize() != 0)
|
|
||||||
{
|
|
||||||
updateGameFileArray();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runRescanAfterLoad)
|
if (sRunRescanAfterLoad)
|
||||||
{
|
{
|
||||||
rescanInProgress.postValue(true);
|
sRescanInProgress.postValue(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadInProgress.postValue(false);
|
sLoadInProgress.postValue(false);
|
||||||
|
|
||||||
if (runRescanAfterLoad)
|
if (sRunRescanAfterLoad)
|
||||||
{
|
{
|
||||||
runRescanAfterLoad = false;
|
sRunRescanAfterLoad = false;
|
||||||
rescan();
|
rescan();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,25 +211,21 @@ public final class GameFileCacheManager
|
|||||||
*/
|
*/
|
||||||
private static void rescan()
|
private static void rescan()
|
||||||
{
|
{
|
||||||
if (gameFileCache == null)
|
if (!sFirstLoadDone)
|
||||||
{
|
{
|
||||||
runRescanAfterLoad = true;
|
sRunRescanAfterLoad = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
String[] gamePaths = GameFileCache.getAllGamePaths();
|
String[] gamePaths = GameFileCache.getAllGamePaths();
|
||||||
|
|
||||||
boolean changed;
|
boolean changed = sGameFileCache.update(gamePaths);
|
||||||
synchronized (gameFileCache)
|
|
||||||
{
|
|
||||||
changed = gameFileCache.update(gamePaths);
|
|
||||||
}
|
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
updateGameFileArray();
|
updateGameFileArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean additionalMetadataChanged = gameFileCache.updateAdditionalMetadata();
|
boolean additionalMetadataChanged = sGameFileCache.updateAdditionalMetadata();
|
||||||
if (additionalMetadataChanged)
|
if (additionalMetadataChanged)
|
||||||
{
|
{
|
||||||
updateGameFileArray();
|
updateGameFileArray();
|
||||||
@ -240,17 +233,29 @@ public final class GameFileCacheManager
|
|||||||
|
|
||||||
if (changed || additionalMetadataChanged)
|
if (changed || additionalMetadataChanged)
|
||||||
{
|
{
|
||||||
gameFileCache.save();
|
sGameFileCache.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rescanInProgress.postValue(false);
|
sRescanInProgress.postValue(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void updateGameFileArray()
|
private static void updateGameFileArray()
|
||||||
{
|
{
|
||||||
GameFile[] gameFilesTemp = gameFileCache.getAllGames();
|
GameFile[] gameFilesTemp = sGameFileCache.getAllGames();
|
||||||
Arrays.sort(gameFilesTemp, (lhs, rhs) -> lhs.getTitle().compareToIgnoreCase(rhs.getTitle()));
|
Arrays.sort(gameFilesTemp, (lhs, rhs) -> lhs.getTitle().compareToIgnoreCase(rhs.getTitle()));
|
||||||
gameFiles.postValue(gameFilesTemp);
|
sGameFiles.postValue(gameFilesTemp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void createGameFileCacheIfNeeded()
|
||||||
|
{
|
||||||
|
// Creating the GameFileCache in the static initializer may be unsafe, because GameFileCache
|
||||||
|
// relies on native code, and the native library isn't loaded right when the app starts.
|
||||||
|
// We create it here instead.
|
||||||
|
|
||||||
|
if (sGameFileCache == null)
|
||||||
|
{
|
||||||
|
sGameFileCache = new GameFileCache();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -301,7 +301,7 @@ public final class MainActivity extends AppCompatActivity
|
|||||||
public void onRefresh()
|
public void onRefresh()
|
||||||
{
|
{
|
||||||
setRefreshing(true);
|
setRefreshing(true);
|
||||||
GameFileCacheManager.startRescan(this);
|
GameFileCacheManager.startRescan();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -368,7 +368,7 @@ public final class MainActivity extends AppCompatActivity
|
|||||||
mViewPager.setCurrentItem(IntSetting.MAIN_LAST_PLATFORM_TAB.getIntGlobal());
|
mViewPager.setCurrentItem(IntSetting.MAIN_LAST_PLATFORM_TAB.getIntGlobal());
|
||||||
|
|
||||||
showGames();
|
showGames();
|
||||||
GameFileCacheManager.startLoad(this);
|
GameFileCacheManager.startLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -96,7 +96,7 @@ public final class MainPresenter
|
|||||||
|
|
||||||
case R.id.menu_refresh:
|
case R.id.menu_refresh:
|
||||||
mView.setRefreshing(true);
|
mView.setRefreshing(true);
|
||||||
GameFileCacheManager.startRescan(activity);
|
GameFileCacheManager.startRescan();
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case R.id.button_add_directory:
|
case R.id.button_add_directory:
|
||||||
@ -146,7 +146,7 @@ public final class MainPresenter
|
|||||||
|
|
||||||
if (sShouldRescanLibrary)
|
if (sShouldRescanLibrary)
|
||||||
{
|
{
|
||||||
GameFileCacheManager.startRescan(mActivity);
|
GameFileCacheManager.startRescan();
|
||||||
}
|
}
|
||||||
|
|
||||||
sShouldRescanLibrary = true;
|
sShouldRescanLibrary = true;
|
||||||
|
@ -79,7 +79,7 @@ public final class TvMainActivity extends FragmentActivity
|
|||||||
if (DirectoryInitialization.shouldStart(this))
|
if (DirectoryInitialization.shouldStart(this))
|
||||||
{
|
{
|
||||||
DirectoryInitialization.start(this);
|
DirectoryInitialization.start(this);
|
||||||
GameFileCacheManager.startLoad(this);
|
GameFileCacheManager.startLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
mPresenter.onResume();
|
mPresenter.onResume();
|
||||||
@ -292,7 +292,7 @@ public final class TvMainActivity extends FragmentActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
DirectoryInitialization.start(this);
|
DirectoryInitialization.start(this);
|
||||||
GameFileCacheManager.startLoad(this);
|
GameFileCacheManager.startLoad();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,7 +303,7 @@ public final class TvMainActivity extends FragmentActivity
|
|||||||
public void onRefresh()
|
public void onRefresh()
|
||||||
{
|
{
|
||||||
setRefreshing(true);
|
setRefreshing(true);
|
||||||
GameFileCacheManager.startRescan(this);
|
GameFileCacheManager.startRescan();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buildRowsAdapter()
|
private void buildRowsAdapter()
|
||||||
@ -313,7 +313,7 @@ public final class TvMainActivity extends FragmentActivity
|
|||||||
|
|
||||||
if (!DirectoryInitialization.isWaitingForWriteAccess(this))
|
if (!DirectoryInitialization.isWaitingForWriteAccess(this))
|
||||||
{
|
{
|
||||||
GameFileCacheManager.startLoad(this);
|
GameFileCacheManager.startLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Platform platform : Platform.values())
|
for (Platform platform : Platform.values())
|
||||||
|
@ -13,8 +13,6 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows")
|
|||||||
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
|
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
|
||||||
add_definitions(-D_CRT_NONSTDC_NO_WARNINGS)
|
add_definitions(-D_CRT_NONSTDC_NO_WARNINGS)
|
||||||
add_definitions(-D_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING)
|
add_definitions(-D_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING)
|
||||||
# The replacement for the old atomic shared_ptr functions was added in C++20, so we can't use it yet
|
|
||||||
add_definitions(-D_SILENCE_CXX20_OLD_SHARED_PTR_ATOMIC_SUPPORT_DEPRECATION_WARNING)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT MSVC)
|
if (NOT MSVC)
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include "UICommon/GameFileCache.h"
|
#include "UICommon/GameFileCache.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <atomic>
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <list>
|
#include <list>
|
||||||
@ -204,7 +203,7 @@ bool GameFileCache::UpdateAdditionalMetadata(std::shared_ptr<GameFile>* game_fil
|
|||||||
if (custom_cover_changed)
|
if (custom_cover_changed)
|
||||||
copy->CustomCoverCommit();
|
copy->CustomCoverCommit();
|
||||||
|
|
||||||
std::atomic_store(game_file, std::move(copy));
|
*game_file = std::move(copy);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,6 @@
|
|||||||
<PreprocessorDefinitions>_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<!--Currently needed for some code in StringUtil used only on Android-->
|
<!--Currently needed for some code in StringUtil used only on Android-->
|
||||||
<PreprocessorDefinitions>_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<!--The replacement for the old atomic shared_ptr functions was added in C++20, so we can't use it yet-->
|
|
||||||
<PreprocessorDefinitions>_SILENCE_CXX20_OLD_SHARED_PTR_ATOMIC_SUPPORT_DEPRECATION_WARNING;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
|
|
||||||
<!--Dolphin-specific definitions-->
|
<!--Dolphin-specific definitions-->
|
||||||
<PreprocessorDefinitions Condition="'$(Platform)'=='x64'">_ARCH_64=1;_M_X86=1;_M_X86_64=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions Condition="'$(Platform)'=='x64'">_ARCH_64=1;_M_X86=1;_M_X86_64=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
Reference in New Issue
Block a user